#region File Description
//-----------------------------------------------------------------------------
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
#endregion

namespace AssetData
{
    /// <summary>
    /// Settings class describes all the tweakable options used
    /// to control the appearance of a particle system.
    /// </summary>
    public class ParticleSettings
    {
        // Name of the texture used by this particle system.
        public string TextureName = null;


        // Maximum number of particles that can be displayed at one time.
        public int MaxParticles = 100;


        // How long these particles will last.
        public TimeSpan Duration = TimeSpan.FromSeconds(1);


        // If greater than zero, some particles will last a shorter time than others.
        public float DurationRandomness = 0;


        // Controls how much particles are influenced by the velocity of the object
        // which created them. You can see this in action with the explosion effect,
        // where the flames continue to move in the same direction as the source
        // projectile. The projectile trail particles, on the other hand, set this
        // value very low so they are less affected by the velocity of the projectile.
        public float EmitterVelocitySensitivity = 1;


        // Range of values controlling how much X and Z axis velocity to give each
        // particle. Values for individual particles are randomly chosen from somewhere
        // between these limits.
        public float MinHorizontalVelocity = 0;
        public float MaxHorizontalVelocity = 0;


        // Range of values controlling how much Y axis velocity to give each particle.
        // Values for individual particles are randomly chosen from somewhere between
        // these limits.
        public float MinVerticalVelocity = 0;
        public float MaxVerticalVelocity = 0;


        // Direction and strength of the gravity effect. Note that this can point in any
        // direction, not just down! The fire effect points it upward to make the flames
        // rise, and the smoke plume points it sideways to simulate wind.
        public Vector3 Gravity = Vector3.Zero;


        // Controls how the particle velocity will change over their lifetime. If set
        // to 1, particles will keep going at the same speed as when they were created.
        // If set to 0, particles will come to a complete stop right before they die.
        // Values greater than 1 make the particles speed up over time.
        public float EndVelocity = 1;


        // Range of values controlling the particle color and alpha. Values for
        // individual particles are randomly chosen from somewhere between these limits.
        public Color MinColor = Color.White;
        public Color MaxColor = Color.White;

        // Used to adjust how quickly the particles fade in and out 6.7 is the default
        // This is applied to the curve however any results above 1 are clipped
        // 6.7 gives a smooth curve with a fairly steep entry and slow exit
        // anything above 6.7 will be steeper but will be at full brightness for longer
        public float FadeFactor = 6.7f;

        // Range of values controlling how fast the particles rotate. Values for
        // individual particles are randomly chosen from somewhere between these
        // limits. If both these values are set to 0, the particle system will
        // automatically switch to an alternative shader technique that does not
        // support rotation, and thus requires significantly less GPU power. This
        // means if you don't need the rotation effect, you may get a performance
        // boost from leaving these values at 0.
        public float MinRotateSpeed = 0;
        public float MaxRotateSpeed = 0;


        // Range of values controlling how big the particles are when first created.
        // Values for individual particles are randomly chosen from somewhere between
        // these limits.
        public float MinStartSize = 100;
        public float MaxStartSize = 100;


        // Range of values controlling how big particles become at the end of their
        // life. Values for individual particles are randomly chosen from somewhere
        // between these limits.
        public float MinEndSize = 100;
        public float MaxEndSize = 100;


        // Alpha blending settings.
        [ContentSerializerIgnore]
        public BlendState BlendState = BlendState.NonPremultiplied;

        // Enumerate BlendStates
        [ContentSerializer(ElementName = "BlendState")]
        public string BlendStateSerializationHelper
        {
            get { return BlendState.Name.Replace("BlendState.", string.Empty); }

            set
            {
                switch (value)
                {
                    case "AlphaBlend": 
                        BlendState = BlendState.AlphaBlend; 
                        break;
                    case "Additive": 
                        BlendState = BlendState.Additive; 
                        break;
                    default: 
                        BlendState = BlendState.NonPremultiplied; 
                        break;
                }
            }
        }

        /////////////////////////////////////////////////////////////////////
        //
        #region Helpers

        /// <summary>
        /// The name of any subfolder used in the Content project to store
        /// the particle images.
        /// Set to a blank string if the images are in the root of the 
        /// content project.
        /// </summary>
        private const string contentTextureSubFolder = "";

        /// <summary>
        /// Returns the likely name of the texture asset used by the content manager.
        /// This assumes there are no duplicate asset names and it has not been 
        /// manually changed.
        /// </summary>
        public string GetAssetNameWithContentPath()
        {
            string imageName = System.IO.Path.GetFileNameWithoutExtension(TextureName);
            if (string.IsNullOrEmpty(contentTextureSubFolder))
            {
                return imageName;
            }
            return System.IO.Path.Combine(contentTextureSubFolder, imageName);
        }

        /// <summary>
        /// Returns the name of the file without a folder.
        /// If the texture name does not include an extension this assumes a type of PNG.
        /// </summary>
        public string GetImageFileName()
        {
            string imageName = System.IO.Path.GetFileName(TextureName);
            if (!string.IsNullOrEmpty(imageName) && !System.IO.Path.HasExtension(imageName))
            {
                imageName += ".png";
            }
            return imageName;
        }

        /// <summary>
        /// Returns a string in the format needed to load the class from the content pipeline.
        /// This is not always the same as the XML format used by the run-time XML serialiser.
        /// </summary>
        public List<string> GetClassInContentXMLFormat()
        {
            List<string> result = new List<string>();
            result.Add("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            result.Add("<XnaContent>");
            result.Add("  <Asset Type=\"AssetData.ParticleSettings\">");
            result.Add("    <BlendState>" + BlendStateSerializationHelper + "</BlendState>");
            result.Add("    <TextureName>" + TextureName + "</TextureName>");
            result.Add("    <MaxParticles>" + System.Xml.XmlConvert.ToString(MaxParticles) + "</MaxParticles>");
            result.Add("    <Duration>" + System.Xml.XmlConvert.ToString(Duration) + "</Duration>");
            result.Add("    <DurationRandomness>" + System.Xml.XmlConvert.ToString(DurationRandomness) + "</DurationRandomness>");
            result.Add("    <EmitterVelocitySensitivity>" + System.Xml.XmlConvert.ToString(EmitterVelocitySensitivity) + "</EmitterVelocitySensitivity>");
            result.Add("    <MinHorizontalVelocity>" + System.Xml.XmlConvert.ToString(MinHorizontalVelocity) + "</MinHorizontalVelocity>");
            result.Add("    <MaxHorizontalVelocity>" + System.Xml.XmlConvert.ToString(MaxHorizontalVelocity) + "</MaxHorizontalVelocity>");
            result.Add("    <MinVerticalVelocity>" + System.Xml.XmlConvert.ToString(MinVerticalVelocity) + "</MinVerticalVelocity>");
            result.Add("    <MaxVerticalVelocity>" + System.Xml.XmlConvert.ToString(MaxVerticalVelocity) + "</MaxVerticalVelocity>");
            result.Add("    <Gravity>" + ParseData.VectorToString(Gravity) + "</Gravity>");
            result.Add("    <EndVelocity>" + System.Xml.XmlConvert.ToString(EndVelocity) + "</EndVelocity>");
            result.Add("    <MinColor>" + ParseData.ColorToXMLHexString(MinColor) + "</MinColor>");
            result.Add("    <MaxColor>" + ParseData.ColorToXMLHexString(MaxColor) + "</MaxColor>");
            result.Add("    <FadeFactor>" + System.Xml.XmlConvert.ToString(FadeFactor) + "</FadeFactor>");
            result.Add("    <MinRotateSpeed>" + System.Xml.XmlConvert.ToString(MinRotateSpeed) + "</MinRotateSpeed>");
            result.Add("    <MaxRotateSpeed>" + System.Xml.XmlConvert.ToString(MaxRotateSpeed) + "</MaxRotateSpeed>");
            result.Add("    <MinStartSize>" + System.Xml.XmlConvert.ToString(MinStartSize) + "</MinStartSize>");
            result.Add("    <MaxStartSize>" + System.Xml.XmlConvert.ToString(MaxStartSize) + "</MaxStartSize>");
            result.Add("    <MinEndSize>" + System.Xml.XmlConvert.ToString(MinEndSize) + "</MinEndSize>");
            result.Add("    <MaxEndSize>" + System.Xml.XmlConvert.ToString(MaxEndSize) + "</MaxEndSize>");
            result.Add("  </Asset>");
            result.Add("</XnaContent>");
            return result;        
        }

        #endregion
        //
        /////////////////////////////////////////////////////////////////////

    }
}
